package br.unifor.mia.graph.setorcensitario;

import java.util.ArrayList;
import java.util.List;

public class CrimeMetrics {

	private List<Node> allNodes;
	
	public CrimeMetrics(List<Node> allNodes) {
		this.allNodes = allNodes;
	}

	/**
	 * @return the nodes
	 */
	public List<Node> getNodes() {
		return allNodes;
	}
	
	public List<Node> getHubs() {

		List<Node> hubs = new ArrayList<Node>();
	
		int maxDegree = 0;
		for (Node node : getNodes()) {
			if (node.getDegree() > maxDegree) {
				maxDegree = node.getDegree();
				hubs.clear();
				hubs.add(node);
			} else {
				if (node.getDegree() == maxDegree) {
					hubs.add(node);
				}
			}
		}
		return hubs;
	}
	
	public void printCrimeHubs() {
		
		List<Node> hubs = getCrimeHubs();
		
		// Imprime Hubs
		System.out.println("###########################");
		for (Node h : hubs) {
			System.out.println("Hub: " + h + " # Crimes: " + h.getNumberOfCrimes());
		}
		System.out.println("###########################");
	}
	
	public List<Node> getCrimeHubs() {

		List<Node> hubs = new ArrayList<Node>();
	
		int maxCrimes = 0;
		for (Node node : getNodes()) {
			if (node.getNumberOfCrimes() > maxCrimes) {
				maxCrimes = node.getNumberOfCrimes();
				hubs.clear();
				hubs.add(node);
			} else {
				if (node.getNumberOfCrimes() == maxCrimes) {
					hubs.add(node);
				}
			}
		}
		return hubs;
	}
	
	public void printEntropy() {

		List<Node> hubs = getHubs();
		
		int nodesSide = getNodes().size();

		// Gera sequencia de graus
		double[] sequence = new double[hubs.get(0).getDegree() + 1];
		for (Node node : getNodes()) {
			sequence[node.getDegree()]++;
		}

		for (int i = 0; i < sequence.length; i++) {
			if (sequence[i] != 0) {
				sequence[i] = sequence[i]/nodesSide;
			}
		}
		
		double entropy = 0;

		for (int i = 0; i < sequence.length; i++) {
			if (sequence[i] != 0) {
				entropy += sequence[i]*(Math.log10(sequence[i])/Math.log10(2));
			}
		}
		
		System.out.println("Entropy: " + -1*entropy);
	}
	
	public void printDegreeSequence() {

		List<Node> hubs = getHubs();

		// Imprime Hubs
		System.out.println("###########################");
		for (Node h : hubs) {
			System.out.println("Hub: " + h + " Grau: " + h.getDegree());
		}
		System.out.println("###########################");

		// Gera sequencia de graus
		int[] sequenciaDeGraus = new int[hubs.get(0).getDegree() + 1];
		for (Node node : getNodes()) {
			sequenciaDeGraus[node.getDegree()]++;
		}

		// Imprime Sequencia de graus
		for (int i = 0; i < sequenciaDeGraus.length; i++) {
			if (sequenciaDeGraus[i] != 0) {
				System.out.println(" [" + i + " = " + sequenciaDeGraus[i] + "] ");
			}
		}
	}
	
	public int[] getCrimesSequence() {

		List<Node> hubs = getCrimeHubs();

		// Gera sequencia de crimes
		int[] sequenciaDeCrimes = new int[hubs.get(0).getNumberOfCrimes() + 1];
		for (Node node : getNodes()) {
			sequenciaDeCrimes[node.getNumberOfCrimes()]++;
		}

		return sequenciaDeCrimes;
	}
	
	public void printCrimesSequence() {

		// Gera sequencia de crimes
		int[] sequenciaDeCrimes = getCrimesSequence();

		// Imprime Sequencia de graus
		for (int i = 0; i < sequenciaDeCrimes.length; i++) {
			if (sequenciaDeCrimes[i] != 0) {
				System.out.println(" [" + i + " = " + sequenciaDeCrimes[i] + "] ");
			}
		}
	}

	public void printCrimesSequence(Node setor) {
		
		List<Node> hubs = getCrimeHubs(setor);

		// Imprime Hubs
		System.out.println("###########################");
		for (Node h : hubs) {
			System.out.println("Hub: " + h + " # Crimes: " + setor.getNumberOfCrimesOf(h));
		}
		System.out.println("###########################");

		// Gera sequencia de crimes
		int[] sequenciaDeCrimes = new int[setor.getNumberOfCrimesOf(hubs.get(0)) + 1];
		for (Node node : getNodes()) {
			sequenciaDeCrimes[setor.getNumberOfCrimesOf(node)]++;
		}

		// Imprime Sequencia de graus
		for (int i = 0; i < sequenciaDeCrimes.length; i++) {
			if (sequenciaDeCrimes[i] != 0) {
				System.out.println(" [" + i + " = " + sequenciaDeCrimes[i] + "] ");
			}
		}
		
	}

	private List<Node> getCrimeHubs(Node setor) {
		
		List<Node> hubs = new ArrayList<Node>();
		
		int maxCrimes = 0;
		for (Node node : getNodes()) {
			if (setor.getNumberOfCrimesOf(node) > maxCrimes) {
				maxCrimes = setor.getNumberOfCrimesOf(node);
				hubs.clear();
				hubs.add(node);
			} else {
				if (setor.getNumberOfCrimesOf(node) == maxCrimes) {
					hubs.add(node);
				}
			}
		}
		return hubs;
	}
}
